package com.thread.laoma;

import java.util.ArrayDeque;
import java.util.Queue;

/**
 * 生产者消费者模式-synchronized方式实现
 * Created by zhuangqi on 17-4-9.
 */
public class PcSyncDemo {
    /**
     *  第一步 ： 找出竞态变量，消费者生产者的竞态变量可以为一个队列
     *  当队列不满时    -->   生产者往队列中增加资源
     *  当队列不为空时  -->   消费者往队列中取出资源
     */
    static class MyBlockingQueue<E>{
        private Queue<E> queue;
        private Integer limit;

        public MyBlockingQueue(Integer limit) {
            this.limit = limit;
            this.queue = new ArrayDeque<>(limit);
        }
        //增加资源
        public synchronized void put(E e) throws InterruptedException {
            if (queue.size() == limit){
                wait();
            }
            queue.add(e);
            notifyAll();
        }
        //消费资源
        public synchronized E take() throws InterruptedException {
            if (queue.isEmpty()){
                wait();
            }
            E e = queue.poll();
            notifyAll();
            return e;
        }
    }

    /**
     *  第二步 ：　建立生产者
     */
    static class Producer implements Runnable{
        private MyBlockingQueue<String> queue;

        public Producer(MyBlockingQueue queue) {
            this.queue = queue;
        }
        @Override
        public void run() {
            int num = 0;
            try {
                while (true) {
                    String task = String.valueOf(num);
                    queue.put(task);
                    System.out.println("produce task " + task);
                    num++;
                    Thread.sleep((int) (Math.random() * 100));
                }
            } catch (InterruptedException e) {
            }
        }
    }
    /**
     *  第三步 ： 建立消费者
     */
    static class Consumer implements Runnable{
        private MyBlockingQueue<String> queue = null;

        public Consumer(MyBlockingQueue<String> queue) {
            this.queue = queue;
        }
        @Override
        public void run() {
            try {
                while (true) {
                    String task = queue.take();
                    System.out.println("handle task " + task);
                    Thread.sleep((int)(Math.random()*100));
                }
            } catch (InterruptedException e) {
            }
        }
    }

    public static void main(String[] args) {
        int size = 10;
        MyBlockingQueue<String> queue = new MyBlockingQueue<>(size);
        Producer producer = new Producer(queue);
        Consumer consumer = new Consumer(queue);
        new Thread(producer).start();
        new Thread(consumer).start();
    }
}
